﻿#region Using directives

using System;
using System.Collections.Generic;
using System.Text;

using Weazel.Gezel.Model.Errors;

#endregion

namespace Weazel.Gezel.Model
{
	public partial class OutPort : IVerifiable		
	{
		public void Verify(ref List<VerificationError> errors, ref List<VerificationWarning> warnings, params object[] arguments)
		{
			//// check if signal connects to a child datapath
      if (parent is Datapath)
      {
        Datapath dp = parent as Datapath;
        foreach (string childdpName in dp.ChildDatapathRefs.Keys)
        {
          string[] connections = dp.ChildDatapathRefs[childdpName];
          for (int i = 0; i < connections.Length; i++)
          {
            string connection = connections[i];
            if (connection == this.localName)
            {
              Block childDp;
              if (Model.Datapaths.ContainsKey(childdpName))
              {
                childDp = Model.Datapaths[childdpName];
              } 
              else
              {
                System.Diagnostics.Debug.Assert(Model.IPBlocks.ContainsKey(childdpName));
                childDp = Model.IPBlocks[childdpName];
              }
              
              Port port = childDp.GetPortAtPosition(i);

              // check if signal is also assigned to from sfg's
              if (this.definers.Count > 0 && port is OutPort)
              {
                errors.Add(buildMultipleDefinersError());
                return; 
              }
              // this check is invalid because it may be wired up to another child ipblock/datapath 
              //else if (port is InPort && this.definers.Count == 0)
              //{
              //  errors.Add(buildNoDefinerError());
              //  return;
              //}
              else if (port is InPort)
              {
                // do nothing
              }
              else
              {
                System.Diagnostics.Debug.Assert(port is OutPort);
                this.outportDriver = port as OutPort;
                return;
              }
            }
          }
        }

        // check if it has any definers at all?
        if (definers.Count == 0)
        {
          errors.Add(buildNoDefinerError());
          return;
        }
      }
    }

    private VerificationError buildNoDefinerError()
    {
      ErrorMessage message = new ErrorMessage();
      message.AddString("Outport ");
      message.AddEntity(this);
      message.AddString(" at position ");
      message.AddPosition(this.startPosition);
      message.AddString(" has no definers");
      return new VerificationError(VerificationErrorType.UnspecifiedError, message);
    }

    private VerificationError buildMultipleDefinersError()
    {
      ErrorMessage message = new ErrorMessage();
      message.AddString("Outport ");
      message.AddEntity(this);
      message.AddString(" at position ");
      message.AddPosition(this.startPosition);
      message.AddString(" has multiple definers");
      return new VerificationError(VerificationErrorType.UnspecifiedError, message);
		}
	}
}
